package xin.nick.common.util;

import xin.nick.common.constant.SystemConstants;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Nick
 */
public class IoUtils {


	private static int readLength = 100;

	private IoUtils() {
	}

	/**
	 * 从一个输入流读取出内容文本
	 * 
	 * @param in
	 *            输入流
	 * @return
	 * @throws IOException
	 */
	public static String read(InputStream in) throws IOException {
		return read(in, SystemConstants.UTF8);
	}

	/**
	 * 从一个输入流中根据指定的编码方式读取出内容文本
	 * 
	 * @param inStream
	 *            输入流
	 * @param encode
	 *            编码方式
	 * @return
	 * @throws IOException
	 */
	public static String read(InputStream inStream, String encode) throws IOException {
		return toString(inStream, encode);
	}

	public static List<String> readLines(InputStream input) throws IOException {
		InputStreamReader reader = new InputStreamReader(input);
		return readLines(reader);
	}

	public static List<String> readLines(InputStream input, String encoding) throws IOException {
		if (encoding == null) {
			return readLines(input);
		} else {
			InputStreamReader reader = new InputStreamReader(input, encoding);
			return readLines(reader);
		}
	}

	public static List<String> readLines(Reader input) throws IOException {
		BufferedReader reader = input instanceof BufferedReader ? (BufferedReader) input : new BufferedReader(input);
		List<String> list = new ArrayList<String>();
		String line = reader.readLine();
		while (line != null) {
			list.add(line);
			line = reader.readLine();
		}
		return list;
	}

	public static void write(String data, OutputStream output) throws IOException {
		if (data != null) {
			output.write(data.getBytes());
		}
	}

	public static void write(byte[] data, OutputStream output) throws IOException {
		if (data != null) {
			output.write(data);
		}
	}

	public static void write(char[] data, OutputStream output) throws IOException {
		if (data != null) {
			output.write(new String(data).getBytes());
		}
	}

	public static void write(char[] data, OutputStream output, String encoding) throws IOException {
		if (data != null) {
			if (encoding == null) {
				write(data, output);
			} else {
				output.write(new String(data).getBytes(encoding));
			}
		}
	}

	public static void write(String data, OutputStream output, String encoding) throws IOException {
		if (data != null) {
			if (encoding == null) {
				write(data, output);
			} else {
				output.write(data.getBytes(encoding));
			}
		}
	}

	public static InputStream toInputStream(byte[] bytes) {
		return new ByteArrayInputStream(bytes);
	}

	public static final byte[] toByteArray(InputStream inStream) throws IOException {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = inStream.read(buff, 0, readLength)) > 0) {
			stream.write(buff, 0, rc);
		}
		byte[] bytes = stream.toByteArray();
		return bytes;
	}

	public static byte[] toByteArray(InputStream input, long size) throws IOException {
		if (size > Integer.MAX_VALUE) {
			throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + Integer.MAX_VALUE);
		}
		return toByteArray(input, (int) size);
	}

	public static byte[] toByteArray(InputStream input, int size) throws IOException {
		if (size < 0) {
			throw new IllegalArgumentException("Size must be equal or greater than zero.");
		}

		if (size == 0) {
			return new byte[0];
		}

		byte[] data = new byte[size];
		int offset = 0;
		int readed;

		while (offset < size && (readed = input.read(data, offset, size - offset)) != -1) {
			offset += readed;
		}

		if (offset != size) {
			throw new IOException("Unexpected readed size. current: " + offset + ", excepted: " + size);
		}
		return data;
	}

	public static final String toString(InputStream inStream) throws IOException {
		return toString(inStream, SystemConstants.UTF8);
	}

	public static final String toString(InputStream inStream, String charset) throws IOException {
		return new String(toByteArray(inStream), charset);
	}

	public static void closeQuietly(OutputStream output) {
		closeQuietly((Closeable) output);
	}

	public static void closeQuietly(Closeable closeable) {
		try {
			if (closeable != null) {
				closeable.close();
			}
		} catch (IOException ioe) {
			// ignore
		}
	}

}
